package clients;

import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.QueueingConsumer;
import com.rabbitmq.client.AMQP.BasicProperties;

import entities.ConnectParameters;

import java.util.ArrayList;
import java.util.UUID;

import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
    

/**
 * @author Idan Mann
 * This class creates a connection object used to communicate with the server.
 * The Constructor reads the properties.config file in the root directory
 * for it's parameters.
 *
 */

public class RPCClient
{
    
  private Connection connection;
  private Channel channel;
  private String requestQueueName = "rpc_queue";
  private String replyQueueName;
  private QueueingConsumer consumer;
    
  public RPCClient() throws Exception
  {
    ConnectionFactory factory = new ConnectionFactory();
    
    ConnectParameters parameters = new ConnectParameters();

    if (parameters.readParameters())
    //if(true)
    {
    	
    	
    	factory.setHost(parameters.getHost());
    	factory.setPort(Integer.parseInt(parameters.getPort()));
    	factory.setVirtualHost(parameters.getVirtualHost());
    	factory.setUsername(parameters.getUsername());
        factory.setPassword(parameters.getPassword());
        
    //	factory.setHost("localhost");
    //	factory.setPort(5672);
        
    	//factory.setHost("localhost");
    	//factory.setPort(5672);
       
        
    }
    else
    {
    	//System.out.println("could not load config.properties");
    	
    	JOptionPane.showMessageDialog(new JPanel(),
			    "לא ניתן להתחבר לשרת.","שגיאה",JOptionPane.ERROR_MESSAGE);
    	
    	System.exit(0);
    	return;
    	
    	
    	
    //	factory.setHost("localhost");
    //	factory.setPort(5672);
    //	factory.setVirtualHost("test");
    //	factory.setUsername("test");
    //    factory.setPassword("test");
        
    }
    
   // factory.setHost("79.182.137.39");
    //factory.setHost("10.0.0.3");
  //  factory.setHost("localhost");
   // factory.setHost("192.117.173.118");
 //   factory.setPort(5672);
    //
    //factory.setUsername("test");
    //factory.setPassword("test");
    connection = factory.newConnection();
    channel = connection.createChannel();

    replyQueueName = channel.queueDeclare().getQueue(); 
    consumer = new QueueingConsumer(channel);
    channel.basicConsume(replyQueueName, true, consumer);
    
  }
  
  /**
   * This method is used to send to the server.
   * message is an ArrayList which holds the command string in it's 0 index
   * followed by other parameters.
   * This ArrayList is then converted to Byte[] and send to the server.
   */
  public ArrayList<Object> call(ArrayList<Object> message) throws Exception 
  {     
	ArrayList<Object> response = null;
    String corrId = UUID.randomUUID().toString();
    
    BasicProperties props = new BasicProperties
                                .Builder()
                                .correlationId(corrId)
                                .replyTo(replyQueueName)
                                .build();
    
    channel.basicPublish("", requestQueueName, props, utilities.Services.convertArrayListToByteArray(message));
    
    while (true)
    {
      QueueingConsumer.Delivery delivery = consumer.nextDelivery();
      if (delivery.getProperties().getCorrelationId().equals(corrId))
      {
        response = utilities.Services.convertByteArrayToArrayList(delivery.getBody());
        break;
      }
    }

    return response; 
  }
    
  public void close() throws Exception
  {
    connection.close();
  }
  
  
  public static void main(String[] argv)
  {
    RPCClient myclient = null;
    ArrayList<Object> response = null;
    try {
    	myclient = new RPCClient();
  
      ArrayList<Object> message = new ArrayList<Object>();
      message.add("Test");
    //  System.out.println("Sending: " + message.get(0));
      response = myclient.call(message); // Send message to server and recieve response
     // System.out.println("Client got: " + ((String)response.get(0)));
 
      
    }
    catch  (Exception e) 
    {
      //e.printStackTrace();
    }
    finally
    {
      if (myclient!= null)
      {
        try
        {
        	myclient.close();
        }
        catch (Exception ignore) {}
      }
    }
  }
}

